package com.example.demo.level3;

import lombok.SneakyThrows;
import org.junit.Test;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

public class LearnThreadPool {

//    private List<Integer> list = getList();

    /**
     * 新建线程池 FixedThreadPool
     */
//    @Test
//    public void threadPool() {
//
//         newFixedThreadPool();
//        Executor executor;
//        AtomicInteger atomicInteger = new AtomicInteger(0);
//
//        executor = newCachedThreadPool();
//        System.out.println(atomicInteger);
//        for (Integer i : list) {
//            executor.execute(() -> {
//                atomicInteger.incrementAndGet();
//            });
//        }
//        System.out.println(atomicInteger.get());
//
//
//        executor = newSingleThreadExecutor();
//        atomicInteger.set(0);
//        for (Integer i : list) {
//            executor.execute(() -> {
//                atomicInteger.incrementAndGet();
//            });
//        }
//        System.out.println(atomicInteger.get());
//
//        executor = newScheduledThreadPool(1);
//        atomicInteger.set(0);
//        for (Integer i : list) {
//            executor.execute(() -> {
//                atomicInteger.incrementAndGet();
//            });
//        }
//        System.out.println(atomicInteger.get());
//    }
//    private List<Integer> getList() {
//        List<Integer> list = new ArrayList<>();
//        for (int i = 0; i < 10000; i++) {
//            list.add(i);
//        }
//        System.out.println("原始数据量: " + list.size());
//        return list;
//    }
    @SneakyThrows
    @Test
    public void newFixedThreadPool() {
        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < 10000; i++) {
            list.add(i);
        }
        System.out.println("原始数据量: " + list.size());
        Executor executor = newFixedThreadPool(1);
        AtomicInteger atomicInteger = new AtomicInteger(0);
        List<Integer> afterList = Collections.synchronizedList(new ArrayList<>());
        long start = System.currentTimeMillis();
        for (Integer i : list) {
            executor.execute(() -> {
//                System.out.println("正在执行 atomicInteger: " + atomicInteger.incrementAndGet());
                afterList.add(i);
            });
        }
        int retry = 10;
        int retryCount = 0;
        while (afterList.size() != list.size()) {
//            System.out.println(atomicInteger.get());
            if (++retryCount >= retry) {
                break;
            }
            Thread.sleep(1000);
        }
        long end = System.currentTimeMillis();
        System.out.println("afterList.size: " + afterList.size());
        System.out.println("done take time: " + (end - start));
    }

    @SneakyThrows
    @Test
    public void newCachedThreadPool() {
        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < 10000; i++) {
            list.add(i);
        }
        System.out.println("原始数据量: " + list.size());
        Executor executor = newCachedThreadPoolExecutor();
        AtomicInteger atomicInteger = new AtomicInteger(0);
        List<Integer> afterList = Collections.synchronizedList(new ArrayList<>());
        long start = System.currentTimeMillis();
        for (Integer i : list) {
            executor.execute(() -> {
//                System.out.println("正在执行 atomicInteger: " + atomicInteger.incrementAndGet());
                afterList.add(i);
            });
        }
        int retry = 10;
        int retryCount = 0;
        while (afterList.size() != list.size()) {
//            System.out.println(atomicInteger.get());
            if (++retryCount >= retry) {
                break;
            }
            Thread.sleep(1000);
        }
        long end = System.currentTimeMillis();
        System.out.println("afterList.size: " + afterList.size());
        System.out.println("done take time: " + (end - start));
    }

    @SneakyThrows
    @Test
    public void newSingleThreadExecutor() {
        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < 10000; i++) {
            list.add(i);
        }
        System.out.println("原始数据量: " + list.size());
        Executor executor = newSingleThreadExecutorExecutor();
        List<Integer> afterList = Collections.synchronizedList(new ArrayList<>());
        long start = System.currentTimeMillis();
        for (Integer i : list) {
            executor.execute(() -> {
                afterList.add(i);
            });
        }
        int retry = 10;
        int retryCount = 0;
        while (afterList.size() != list.size()) {
//            System.out.println(atomicInteger.get());
            if (++retryCount >= retry) {
                break;
            }
            Thread.sleep(1000);
        }
        long end = System.currentTimeMillis();
        System.out.println("afterList.size: " + afterList.size());
        System.out.println("done take time: " + (end - start));
    }

    @SneakyThrows
    @Test
    public void newScheduledThreadPool() {
        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < 10000; i++) {
            list.add(i);
        }
        System.out.println("原始数据量: " + list.size());
        Executor executor = newScheduledThreadPool(1);
        AtomicInteger atomicInteger = new AtomicInteger(0);
        List<Integer> afterList = Collections.synchronizedList(new ArrayList<>());
        long start = System.currentTimeMillis();
        for (Integer i : list) {
            executor.execute(() -> {
//                System.out.println("正在执行 atomicInteger: " + atomicInteger.incrementAndGet());
                afterList.add(i);
            });
        }
        int retry = 10;
        int retryCount = 0;
        while (afterList.size() != list.size()) {
//            System.out.println(atomicInteger.get());
            if (++retryCount >= retry) {
                break;
            }
            Thread.sleep(1000);
        }
        long end = System.currentTimeMillis();
        System.out.println("afterList.size: " + afterList.size());
        System.out.println("done take time: " + (end - start));
    }

    public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                0L, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<>());
    }

    public static ExecutorService newCachedThreadPoolExecutor() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                60L, TimeUnit.SECONDS,
                new SynchronousQueue<>());
    }

    public static ExecutorService newSingleThreadExecutorExecutor() {
//        return new FinalizableDelegatedExecutorService
//                (new ThreadPoolExecutor(1, 1,
//                        0L, TimeUnit.MILLISECONDS,
//                        new LinkedBlockingQueue<Runnable>()));
        return new ThreadPoolExecutor(1, 1,
                0L, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<>());
    }

    public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
        return new ScheduledThreadPoolExecutor(corePoolSize);
    }

}
